<?php

namespace tmcore\services\crud\generators;

use app\common\model\dict\DictType;
use tmcore\services\crud\enum\SearchEnum;
use tmcore\services\crud\UtilService;

class VueIndexView extends Generate
{

    /**
     * @var string
     */
    protected string $fileType = 'vue';

    /**
     * 替换变量
     */
    public function replaceContent()
    {
        $search = [
            '{SEARCH_VIEW}',
            '{BUTTON_HEADER}',
            '{TABLE_HEADER}',
            '{LISTS_VIEW}',
            '{TABLE_BTN}',
            '{DIALOG_VIEW}',
            '{CAMEL_CLASS_NAME}',
            '{JS_USE}',
            '{JS_HEADER}',
            '{SEARCH_QUERY}',
            '{JS_CONTENT}',
            '{JS_FOOTER}',
            '{PK}'
        ];

        $replace = [
            $this->getSearchViewContent(),
            $this->getButtonHeaderContent(),
            $this->getTableHeaderContent(),
            $this->getListsViewContent(),
            $this->getTableBtnContent(),
            $this->getDialogViewContent(),
            UtilService::lcfirst($this->getCamelClassName()),
            $this->getJsUseContent(),
            $this->getJsHeaderContent(),
            $this->getQueryParamsContent(),
            $this->getJsContentContent(),
            $this->getJsFooterContent(),
            $this->getPk()
        ];

        $tpl = $this->isTypeTree()?'indexTree':'index';

        $content = UtilService::replaceFileContent($search, $replace, $this->getStub($tpl));

        $this->setContent($content);
    }

    /**
     * 返回模板路径
     * @param string $type
     * @return mixed|string|string[]
     */
    public function getStub(string $type = 'edit')
    {
        $basePath = 'vue/views/';

        $stubs = [
            'search_input' => $this->getTplPath($basePath . 'search/input'),
            'search_select' => $this->getTplPath($basePath . 'search/select'),
            'search_datePicker' => $this->getTplPath($basePath . 'search/datePicker'),
            'table_areaSelect' => $this->getTplPath($basePath . 'table/areaSelect'),
            'table_checkbox' => $this->getTplPath($basePath . 'table/checkbox'),
            'table_datePicker' => $this->getTplPath($basePath . 'table/datePicker'),
            'table_default' => $this->getTplPath($basePath . 'table/default'),
            'table_number' => $this->getTplPath($basePath . 'table/number'),
            'table_fileSelect' => $this->getTplPath($basePath . 'table/fileSelect'),
            'table_fileSelectMul' => $this->getTplPath($basePath . 'table/fileSelectMul'),
            'table_imageSelect' => $this->getTplPath($basePath . 'table/imageSelect'),
            'table_imageSelectMul' => $this->getTplPath($basePath . 'table/imageSelectMul'),
            'table_radio' => $this->getTplPath($basePath . 'table/radio'),
            'table_select' => $this->getTplPath($basePath . 'table/select'),
            'table_selectMul' => $this->getTplPath($basePath . 'table/selectMul'),
            'table_videoSelect' => $this->getTplPath($basePath . 'table/videoSelect'),
            'table_videoSelectMul' => $this->getTplPath($basePath . 'table/videoSelectMul'),
            'table_userSelect' => $this->getTplPath($basePath . 'table/userSelect'),
            'table_timePicker' => $this->getTplPath($basePath . 'table/timePicker'),
            'page_addBtn' => $this->getTplPath($basePath . 'page/index/addBtn'),
            'page_addFun' => $this->getTplPath($basePath . 'page/index/addFun'),
            'page_batchDeleteFun' => $this->getTplPath($basePath . 'page/index/batchDeleteFun'),
            'page_deleteBtn' => $this->getTplPath($basePath . 'page/index/deleteBtn'),
            'page_deleteBatchBtn' => $this->getTplPath($basePath . 'page/index/deleteBatchBtn'),
            'page_deleteFun' => $this->getTplPath($basePath . 'page/index/deleteFun'),
            'page_editBtn' => $this->getTplPath($basePath . 'page/index/editBtn'),
            'page_editFun' => $this->getTplPath($basePath . 'page/index/editFun'),
            'page_detailBtn' => $this->getTplPath($basePath . 'page/index/detailBtn'),
            'page_detailFun' => $this->getTplPath($basePath . 'page/index/detailFun'),
            'page_exportBtn' => $this->getTplPath($basePath . 'page/index/exportBtn'),
            'page_importBtn' => $this->getTplPath($basePath . 'page/index/importBtn'),
            'page_tableDelHeader' => $this->getTplPath($basePath . 'page/index/tableDelHeader'),
            'page_tableHeader' => $this->getTplPath($basePath . 'page/index/tableHeader'),
            'page_tableTreeHeader' => $this->getTplPath($basePath . 'page/index/tableTreeHeader'),
            'page_editDialog' => $this->getTplPath($basePath . 'page/index/editDialog'),
            'page_detailDialog' => $this->getTplPath($basePath . 'page/index/detailDialog'),
            'index' => $this->getTplPath($basePath . 'index'),
            'indexTree' => $this->getTplPath($basePath . 'indexTree'),
        ];

        return $type ? $stubs[$type] : $stubs;
    }

    /**
     * 设置文件路径
     */
    public function setFilePath()
    {
        $name =  'index.' . $this->fileType;
        $this->setCrudFileName($name);

        $module_path = dirname($this->rootPath) . '/admin/src/views/';
        if (!empty($this->classDir)) $module_path .= $this->classDir . '/';
        $module_path .= UtilService::lcfirst($this->getCamelClassName()) . '/';
        $this->setCrudModuleFilePath($module_path);

        $data_path = $this->crudDir . 'vue/src/views/';
        if (!empty($this->classDir)) $data_path .= $this->classDir . '/';
        $data_path .= UtilService::lcfirst($this->getCamelClassName()) . '/';
        $this->setCrudDataFilePath($data_path);
    }

    /**
     * 获取搜索内容
     * @return string
     */
    public function getSearchViewContent()
    {
        $content = '';
        $tab2 = UtilService::tab(2);
        foreach ($this->crudColumn as $key => $value) {
            if ($value['is_query'] && (!$value['is_pk']) && in_array($value['view_type'], SearchEnum::ACCEPT_FORM_TYPE)) {

                $search = [
                    '{COLUMN_COMMENT}',
                    '{COLUMN_NAME}',
                    '{FOREACH_SELECT}'
                ];

                $select_content = '';

                if($value['dict_type']) {
                    $dict_type = DictType::where(['id' => $value['dict_type']])->value('value');
                    $select_content = <<<CONTENT
{$tab2}<el-option 
{$tab2}    v-for="(item, index) in dictDataList.{$dict_type}"
{$tab2}    :key="index" 
{$tab2}    :label="item.name"
{$tab2}    :value="item.value"
{$tab2}/>
CONTENT;
                } else {
                    if(!empty($value['extra']['list'])) {
                        foreach ($value['extra']['list'] as $k => $val) {
                            $select_content .= <<<CONTENT
{$tab2}<el-option label="{$val['name']}" value="{$val['value']}" />
CONTENT. PHP_EOL;
                        }
                        $select_content = substr($select_content, 0, -1);
                    }
                }

                $replace = [
                    $this->getTableColumnComment($value['column_comment']),
                    $value['column_name'],
                    $select_content
                ];

                $searchStubType = $value['view_type'];

                if ($value['view_type'] == 'radio') {
                    $searchStubType = 'select';
                }

                $content .= UtilService::replaceFileContent($search, $replace, $this->getStub('search_' . $searchStubType)) . PHP_EOL;
            }
        }

        if (!empty($content)) {
            $content = substr($content, 0, -1);
        }

        $content = UtilService::setBlankSpace($content, '                ');
        return $content;
    }

    /**
     * 获取按钮头部内容
     * @return string
     */
    public function getButtonHeaderContent() {
        $content = '';

        if($this->crudData['is_export']) {
            $class_name = UtilService::lcfirst($this->crudData['class_name']);
            $content .= UtilService::replaceFileContent(['{PERMS_EXPORT}' , '{CAMEL_CLASS_NAME}'], [$this->getPermsNameContent() . '/export', $class_name], $this->getStub('page_exportBtn')) . PHP_EOL;
        }

        if($this->crudData['is_import']) {
            $class_name = UtilService::lcfirst($this->crudData['class_name']);
            $content .= UtilService::replaceFileContent(['{PERMS_IMPORT}', '{TEMPLATE_URL}', '{CAMEL_CLASS_NAME}'], [$this->getPermsNameContent() . '/import',  "getUrl('" . '/uploads/excel/' . $this->crudData['table_comment'] . '导入示例.xlsx' . "')" , $class_name], $this->getStub('page_importBtn')) . PHP_EOL;
        }

        if (!empty($content)) {
            $content = substr($content, 0, -1);
        }

        return $content;
    }

    /**
     * 获取表格头部内容
     * @return string
     */
    public function getTableHeaderContent() {

        $content = '';

        if($this->crudData['is_insert']) {
            $content .= UtilService::replaceFileContent(['{PERMS_ADD}'], [$this->getPermsNameContent() . '/add'], $this->getStub('page_addBtn')) . PHP_EOL;
        }

        if($this->crudData['is_delete'] && !$this->isTypeTree()) {
            $content .= UtilService::replaceFileContent(['{PERMS_DELETE}'], [$this->getPermsNameContent() . '/delete'], $this->getStub('page_deleteBatchBtn')) . PHP_EOL;
        }

        if($this->isTypeTree()) {
            $content .= UtilService::replaceFileContent(['{TREE_ID}'], [$this->treeConfig['tree_id']], $this->getStub('page_tableTreeHeader')) . PHP_EOL;
        } else {
            if($this->crudData['is_delete']) {
                $content .= UtilService::replaceFileContent(['{PERMS_DELETE}'], [$this->getPermsNameContent() . '/delete'], $this->getStub('page_tableDelHeader')) . PHP_EOL;
            } else {
                $content .= UtilService::replaceFileContent([], [], $this->getStub('page_tableHeader')) . PHP_EOL;
            }
        }

        if (!empty($content)) {
            $content = substr($content, 0, -1);
        }

        return $content;
    }


    /**
     * 获取列表内容
     * @return string
     */
    public function getListsViewContent()
    {
        $content = '';
        $form_type_arr = ['fileSelect', 'imageSelect', 'videoSelect', 'select'];
        foreach ($this->crudColumn as $key=>$value) {
            if($value['is_list']) {

                $search = [
                    '{COLUMN_COMMENT}',
                    '{COLUMN_NAME}',
                    '{COLUMN_NAME_DESC}',
                ];

                $replace = [
                    $this->getTableColumnComment($value['column_comment']),
                    $value['column_name'],
                    $value['column_name'] . '_' . UtilService::lower($this->attrPrefix),
                ];

                $tableStubType = $value['view_type'];

                if ($value['view_type'] == 'input' || $value['view_type'] == 'number' || $value['view_type'] == 'textarea' || $value['view_type'] == 'editor' || $value['view_type'] == 'treeSelect') {
                    $tableStubType = 'default';
                    if($value['column_type'] == 'decimal') $tableStubType = 'number';
                }

                if(in_array($tableStubType, $form_type_arr) && !empty($value['extra']['multiple'])) {
                    $tableStubType .= 'Mul';
                }

                $content .= UtilService::replaceFileContent($search, $replace, $this->getStub('table_' . $tableStubType)) . PHP_EOL;

            }
        }
        if (!empty($content)) {
            $content = substr($content, 0, -1);
        }
        return UtilService::setBlankSpace($content, '                ');
    }

    /**
     * 获取列表按钮
     * @return string
     */
    public function getTableBtnContent()
    {
        $content = '';

        if($this->crudData['is_update']) {
            $content .= UtilService::replaceFileContent(['{PERMS_EDIT}'], [$this->getPermsNameContent() . '/edit'], $this->getStub('page_editBtn')) . PHP_EOL;
        }

        if($this->crudData['is_delete']) {
            $content .= UtilService::replaceFileContent(['{PERMS_DELETE}'], [$this->getPermsNameContent() . '/delete'], $this->getStub('page_deleteBtn')) . PHP_EOL;
        }

        if($this->crudData['is_detail']) {
            $content .= UtilService::replaceFileContent(['{PERMS_DETAIL}'], [$this->getPermsNameContent() . '/detail'], $this->getStub('page_detailBtn')) . PHP_EOL;
        }

        if (!empty($content)) {
            $content = substr($content, 0, -1);
        }

        return $content;
    }

    /**
     * 引用前端组件内容
     * @return string
     */
    public function getDialogViewContent()
    {
        $content = '';

        if($this->crudData['component_type'] != 2 && $this->crudData['is_update']) {
            $content .= UtilService::replaceFileContent([],[],$this->getStub('page_editDialog')) . PHP_EOL;
        }

        if($this->crudData['component_type'] != 2 && $this->crudData['is_detail']) {
            $content .= UtilService::replaceFileContent([],[],$this->getStub('page_detailDialog')) . PHP_EOL;
        }

        if (!empty($content)) {
            $content = substr($content, 0, -1);
        }

        return $content;
    }

    /**
     * 获取JS_USE内容
     * @return string
     */
    public function getJsUseContent()
    {
        $content = '';

        // 拼接api调用
        $apiClass = UtilService::lcfirst($this->crudData['class_name']);

        // 路由跳转函数
        if ($this->crudData['component_type'] == 2) {
            $content .= <<<CONTENT
import { useRouter } from 'vue-router';
CONTENT. PHP_EOL;
        }

        // 关联数据字典
        if(!empty($this->params['crud_column_check']['is_dict'])) {
            $content .= <<<CONTENT
import { getCrudDictDataList } from '/@/api/crud/table';
CONTENT . PHP_EOL;
        }

        // 工具函数调用
        if (!empty($this->params['crud_column_check']['is_index_datePicker']) || !empty($this->params['crud_column_check']['is_index_imageSelect'])) {
            $funContent = '{ ';
            if(!empty($this->params['crud_column_check']['is_index_imageSelect'])) $funContent .= 'getUrl, ';
            if(!empty($this->params['crud_column_check']['is_index_datePicker'])) $funContent .= 'dateToString, isNumber, ';
            $funContent = substr($funContent, 0, -2);
            $funContent .= ' }';

            $content .= <<<CONTENT
import $funContent from '/@/utils/util';
CONTENT . PHP_EOL;
        }

        $apiContent = '{ ' . $apiClass . 'List';
        if($this->crudData['is_delete']) $apiContent .= ', ' . $apiClass . 'Delete';
        if($this->crudData['is_export']) $apiContent .= ', ' . $apiClass . 'Export';
        if($this->crudData['is_import']) $apiContent .= ', ' . $apiClass . 'Import';
        $apiContent .= ' }';

        $apiDir = UtilService::lower($this->classDir) . ($this->classDir ? '/' : '') . UtilService::lcfirst($this->crudData['class_name']);

        $content .= <<<CONTENT
import {$apiContent} from '/@/api/{$apiDir}';
CONTENT . PHP_EOL;
        
        $view_dir = ($this->classDir ? $this->classDir . '/':'') . UtilService::lcfirst($this->getCamelClassName());

        if($this->crudData['component_type'] != 2 && ($this->crudData['is_insert'] || $this->crudData['is_update'])) {
            $content .= <<<CONTENT
import EditDialog from '/@/views/{$view_dir}/component/edit.vue';
CONTENT . PHP_EOL;
        }

        if($this->crudData['component_type'] != 2 && $this->crudData['is_detail']) {
            $content .= <<<CONTENT
import DetailDialog from '/@/views/{$view_dir}/component/detail.vue';
CONTENT . PHP_EOL;
        }

        if (!empty($content)) {
            $content = substr($content, 0, -1);
            $content .= PHP_EOL;
        }

        return $content;
    }

    /**
     * 获取JS_HEADER内容
     * @return string
     */
    public function getJsHeaderContent()
    {
        $content = '';

        if($this->crudData['component_type'] != 2 && $this->crudData['is_update']) {
            $content .= <<<CONTENT
const editDialogRef = ref();

const showEditDialog = ref(false);
CONTENT . PHP_EOL . PHP_EOL;
        }

        if($this->crudData['component_type'] != 2 && $this->crudData['is_detail']) {
            $content .= <<<CONTENT
const detailDialogRef = ref();

const showDetailDialog = ref(false);
CONTENT . PHP_EOL . PHP_EOL;
        }

        if($this->crudData['component_type'] == 2) {
            $content .= <<<CONTENT
const router = useRouter();
CONTENT . PHP_EOL . PHP_EOL;
        }

        if($this->isTypeTree()) {
            $content .= <<<CONTENT
const tableRef = ref();
CONTENT . PHP_EOL . PHP_EOL;
        }

        if (!empty($content)) {
            $content = substr($content, 0, -1);
        }

        return $content;
    }


    /**
     * 获取查询条件内容
     * @return string
     */
    public function getQueryParamsContent()
    {
        $content = '';

        foreach ($this->crudColumn as $key => $value) {
            if($value['is_query'] && !$value['is_pk']) {
                $content .= $value['column_name'] . ": ''," . PHP_EOL;
            }
        }
        if (!empty($content)) {
            $content = substr($content, 0, -1);
        }

        return UtilService::setBlankSpace($content, '        ');
    }

    /**
     * 获取JS内容
     * @return string
     */
    public function getJsContentContent()
    {
        $content = '';

        $tab1 = UtilService::tab(1);

        // 关联数据字典
        if(!empty($this->params['crud_column_check']['is_dict'])) {
            $dict_params = '';
            foreach ($this->crudColumn as $value) {
                if($value['dict_type'] && $value['is_query'] && in_array($value['view_type'], SearchEnum::ACCEPT_FORM_TYPE)) {
                    $dict_params .= ($value['dict_type'] . '@' . $value['column_name'] . ',');
                }
            }
            $dict_params = substr($dict_params, 0, -1);

            $content .= <<<CONTENT
const dictDataList:any = ref({});

const getDictList = async () => {
{$tab1}dictDataList.value = await getCrudDictDataList({dict_types:'{$dict_params}'});
};
CONTENT . PHP_EOL . PHP_EOL;
        }

        if($this->crudData['is_delete'] && !$this->isTypeTree()) {
            $content .= <<<CONTENT
// 选中数据
const selectData = ref<any[]>([]);

// 选中回调事件
const handleSelectionChange = (val: any[]) => {
    selectData.value = val.map(({ {PK} }) => {PK});
}
CONTENT . PHP_EOL . PHP_EOL;
        }

        $tab2 = UtilService::tab(2);
        $tab3 = UtilService::tab(3);
        $tpl_arr = ['Dialog', 'Page', 'Drawer'];

        if($this->crudData['is_insert']) {
            $add_content ='';
            if($this->crudData['component_type'] == 1 || $this->crudData['component_type'] == 3) {
                $add_content .= <<<CONTENT
{$tab1}showEditDialog.value = true;
{$tab1}nextTick(() => {
{$tab2}editDialogRef.value?.open('add');
{$tab1}});
CONTENT;
            } else {
                $path = '/' . $this->getPermsNameContent() . '/edit';
                $add_content .= <<<CONTENT
{$tab1}router.push({ path: '{$path}'})
CONTENT;
            }

            $content .= UtilService::replaceFileContent(['{ADD_FUN_CONTENT}'],[$add_content],$this->getStub('page_addFun')) . PHP_EOL . PHP_EOL;
        }

        if($this->crudData['is_update']) {
            $edit_content ='';
            $tpl_type = $tpl_arr[($this->crudData['component_type'] - 1)];
            if($this->crudData['component_type'] == 1 || $this->crudData['component_type'] == 3) {
                $edit_content .= <<<CONTENT
{$tab1}showEditDialog.value = true;
{$tab1}nextTick(() => {
{$tab2}editDialogRef.value?.setFormData(row, () => {
{$tab3}editDialogRef.value?.open('edit');
{$tab2}});
{$tab1}});
CONTENT;
            } else {
                $path = '/' . $this->getPermsNameContent() . '/edit';
                $edit_content .= <<<CONTENT
{$tab1}router.push({ path: '{$path}', query: { id: row.{$this->getPk()} }})
CONTENT;
            }

            $content .= UtilService::replaceFileContent(['{EDIT_FUN_CONTENT}'],[$edit_content],$this->getStub('page_editFun')) . PHP_EOL . PHP_EOL;
        }

        if($this->crudData['is_detail']) {
            $detail_content ='';
            if($this->crudData['component_type'] == 1 || $this->crudData['component_type'] == 3) {
                $detail_content .= <<<CONTENT
{$tab1}showDetailDialog.value = true;
{$tab1}nextTick(() => {
{$tab2}detailDialogRef.value?.setFormData(row, () => {
{$tab3}detailDialogRef.value?.open();
{$tab2}});
{$tab1}});
CONTENT;
            } else {
                $path = '/' . $this->getPermsNameContent() . '/detail';
                $detail_content .= <<<CONTENT
{$tab1}router.push({ path: '{$path}', query: { id: row.{$this->getPk()} }})
CONTENT;
            }

            $content .= UtilService::replaceFileContent(['{DETAIL_FUN_CONTENT}'],[$detail_content],$this->getStub('page_detailFun')) . PHP_EOL . PHP_EOL;
        }

        if($this->crudData['is_delete']) {
            $content .= UtilService::replaceFileContent(['{CAMEL_TABLE_NAME}', '{PK}'], [UtilService::lcfirst($this->crudData['class_name']), $this->getPk()], $this->getStub('page_deleteFun')) . PHP_EOL . PHP_EOL;
        }

        if (!empty($content)) {
            $content = substr($content, 0, -2);
        }

        return $content;
    }

    /**
     * 获取JS结尾
     * @return string
     */
    public function getJsFooterContent()
    {
        $tab1 = UtilService::tab(1);
        $content = <<<CONTENT
{$tab1}getTableList();
CONTENT;
        if(!empty($this->params['crud_column_check']['is_dict'])) {
            $content .= PHP_EOL . <<<CONTENT
{$tab1}getDictList();
CONTENT;
        }
        return $content;
    }

    /**
     * 路由权限内容
     * @return string
     */
    public function getPermsNameContent()
    {
        return UtilService::lower($this->classDir) . '/' . UtilService::lcfirst($this->crudData['class_name']);
    }

}